package com;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;

import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;

import com.bean.GameModel;
import com.utils.ExcelUtils;
import com.utils.KV;
/**
 * 配置管理类
 * 
 * 1对重载配置
 * {
 * 	TODO 暂时未考虑线程安全
 * 	对servlet的工程 暂时还没想法怎么保证脏读 
 * 	脏读: 从配置获得2次配置 有可能第一次是新的 第二次是旧的
 * 	对可控线程的工程，更新之后保存一个副本 然后给每个线程发一个消息 让他们自己去更新 
 * }
 * @author Administrator
 *
 */
public class ConfigManager {
	/**model列表**/
	private List<Class<? extends GameModel>> modeList = new ArrayList<Class<? extends GameModel>>();
	
	/** 所有通过模板文件转换而成的模板对象的实例 */
	private Map<Class<?>, Map<Integer, GameModel>> templateObjects = new ConcurrentHashMap<Class<?>, Map<Integer, GameModel>>();
	/** key1:class key2:索引名字(TemplateConfig的字段) key3:索引值 **/
	private Map<Class<?>, Map<String, Map<String, List<GameModel>>>> templatesList = new ConcurrentHashMap<Class<?>, Map<String, Map<String, List<GameModel>>>>();
	/** key1:class key2:索引名字(TemplateConfig的字段) key3:索引值 **/
	private Map<Class<?>, Map<String, Map<String, Set<GameModel>>>> templatesSet = new ConcurrentHashMap<Class<?>, Map<String, Map<String, Set<GameModel>>>>();
	/** key1:class key2:排序的名字**/
	private Map<Class<?>, Map<String, List<GameModel>>> templatesIndexList = new ConcurrentHashMap<Class<?>, Map<String,List<GameModel>>>();

	/**配置文件路径**/
	private String resourceFolder;

	/**拼索引用的stringBuilder**/
	private ThreadLocal<StringBuilder> sbLocation =ThreadLocal.withInitial(new Supplier<StringBuilder>() {
		public StringBuilder get() {
			return new StringBuilder();
		}
	});
	
	
	

	/**
	 * 初始化配置文件，并加载excel脚本
	 * 
	 */
	public void init() {
		for (Class<? extends GameModel> model : modeList) {
			try {
				loadClass(model);
			} catch (Throwable e) {
				System.out.println(model);
				throw new RuntimeException(e);
			}
		}
	}
	
	
	public void addModel(Class<? extends GameModel> model)
	{
		this.modeList.add(model);
	}

	@SuppressWarnings({ "static-access", "unchecked" })
	public void loadClass(Class<? extends GameModel> clas) throws InstantiationException, IllegalAccessException {
		GameModel model = clas.newInstance();
		String[] name = model.getFileName().split("_");
		String excelName = name[0].trim();
		String sheetName = name[1].trim();
		String xlsPath = resourceFolder + File.separator + excelName;
		Workbook book = ExcelUtils.loadExcel(xlsPath);
		Sheet sheet = book.getSheet(sheetName);
		@SuppressWarnings("rawtypes")
		List list = new ArrayList();
		Map<String, Map<String, List<GameModel>>> listMap = null;
		Map<String, Map<String, Set<GameModel>>> setMap = null;
		Map<String, List<GameModel>> indexlist = null;
		String[] indexs = model.getComplexIndex();
		if (indexs != null) {
			listMap = new HashMap<String, Map<String, List<GameModel>>>();
		}
		if (model.isHash()) {
			setMap = new HashMap<String, Map<String, Set<GameModel>>>();
		}
		model.initModels(sheet, model.getClass(), list, listMap, setMap);
		for (Object obj : list) {
			GameModel temp = (GameModel) obj;
			temp.init();
		}

		Map<Integer, GameModel> map = new HashMap<Integer, GameModel>();
		GameModel.listToMap(list, map, GameModel.PRIMARY_KEY);
		templateObjects.put(model.getClass(), map);
		if (listMap != null) {
			templatesList.put(model.getClass(), listMap);
		}
		if (setMap != null) {
			templatesSet.put(model.getClass(), setMap);
		}
		
		
		KV<String, Comparator<GameModel>>[] kvs = model.getSort();
		if (kvs != null) {
			//对同一类型的主键值排序
			for(KV<String, Comparator<GameModel>> kv:kvs)
			{
				Map<String, List<GameModel>> temp = listMap.get(kv.getK());
				for(List<GameModel> listTemp:temp.values())
				{
					Collections.sort(listTemp, kv.getV());
				}
			}
			//对主键排序
			indexlist = new HashMap<String, List<GameModel>>();
			for(KV<String, Comparator<GameModel>> kv:kvs)
			{
				List<GameModel> sortlist = new ArrayList<GameModel>();
				Map<String, List<GameModel>> temp = listMap.get(kv.getK());
				for(List<GameModel> temp1:temp.values())
				{
					for(GameModel temp2:temp1)
					{
						sortlist.add(temp2);
					}
				}
				Collections.sort(sortlist, kv.getV());
				indexlist.put(kv.getK(), sortlist);
			}
			templatesIndexList.put(clas, indexlist);
		}
	}

	/**
	 * 重载配置
	 * @param clas
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 */
	public void reload(Class<? extends GameModel> clas) throws InstantiationException, IllegalAccessException {
		loadClass(clas);
	}

	public void setResourceFolder(String resourceFolder) {
		this.resourceFolder = resourceFolder;
	}

	/**
	 * @param <T>
	 * @param clazz
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public <T extends GameModel> T getById(Class<?> clazz, int id) {
		Map<Integer, GameModel> map = templateObjects.get(clazz);
		GameModel modle = map.get(id);
		if (modle == null)
			return null;
		return (T) modle;
	}

	/**
	 * @param <T>
	 * @param clazz
	 * @return
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public <T extends GameModel> Collection<T> getAll(Class<?> clazz) {
		Map<Integer, GameModel> map = templateObjects.get(clazz);
		if (map == null)
			return null;
		return (Collection) map.values();
	}

	/**
	 * 根据复合索引 找到一组配置
	 * 
	 * @param indexName
	 *            索引名称
	 * @param indexVal
	 *            索引的值
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public <T extends GameModel> List<T> getTemplateListByIndex(Class<T> clazz, String indexName, Object... indexVal) {
		// Map<Class<?>, Map<String, Map<String, List<TemplateConfig>>>>
		// templatesList;
		StringBuilder sb = sbLocation.get();
		for (Object obj : indexVal) {
			sb.append(obj);
			sb.append(GameModel.CONST_SPIT);
		}
		String values = sb.toString();
		sb.delete(0, values.length());
		Map<String, Map<String, List<GameModel>>> map1 = this.templatesList.get(clazz);
		if (map1 == null)
			return null;
		Map<String, List<GameModel>> map2 = map1.get(indexName);
		if (map2 == null)
			return null;
		return (List) map2.get(values);
	}
	
	
	
	/**
	 * 获得根据索引排序后的一组配置
	 * @param clazz
	 * @param indexName
	 * @return
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public <T extends GameModel> List<T> getTemplateSortListByIndex(Class<T> clazz, String indexName)
	{
		return (List)templatesIndexList.get(clazz).get(indexName);
	}
	
	
	
	
	
	/**
	 * 根据复合索引 找到一组配置
	 * 
	 * @param indexName
	 *            索引名称
	 * @param indexVal
	 *            索引的值
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public <T extends GameModel> Set<T> getTemplateSetByIndex(Class<T> clazz, String indexName, Object... indexVal) {
		StringBuilder sb = sbLocation.get();
		for (Object obj : indexVal) {
			sb.append(obj);
			sb.append(GameModel.CONST_SPIT);
		}
		String values = sb.toString();
		sb.delete(0, values.length());
		Map<String, Map<String, Set<GameModel>>> map1 = this.templatesSet.get(clazz);
		if (map1 == null)
			return null;
		Map<String, Set<GameModel>> map2 = map1.get(indexName);
		if (map2 == null)
			return null;
		Set<GameModel> set = map2.get(values);
		if (set == null)
			return null;
		return (Set) set;
	}

	/**
	 * 根据复合索引找到一个配置
	 * 
	 * @param clazz
	 * @param indexName
	 *            索引名称
	 * @param indexVal
	 *            索引的值
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public <T extends GameModel> T getTemplateByIndex(Class<T> clazz, String indexName, Object... indexVal) {
		StringBuilder sb = sbLocation.get();
		for (Object obj : indexVal) {
			sb.append(obj);
			sb.append(GameModel.CONST_SPIT);
		}
		String values = sb.toString();
		sb.delete(0, values.length());
		Map<String, Map<String, List<GameModel>>> map1 = this.templatesList.get(clazz);
		if (map1 == null)
			return null;
		Map<String, List<GameModel>> map2 = map1.get(indexName);
		if (map2 == null)
			return null;
		List<GameModel> list = map2.get(values);
		if (list == null || list.isEmpty())
			return null;
		return (T) list.get(0);
	}

	public static void main(String[] args) {
		// Map<Object, Integer> map = new HashMap<Object, Integer>();
		//
		// map.put(new Object[]{1,2}, 44);
		// Integer a = map.get(new Object[]{1,2});
		// System.out.println();

		for (int i = 0; i < 1000000; i++) {
			String.valueOf(55);
		}
		String gaga = "gaga";

		StringBuilder sb = new StringBuilder();
		long start = System.currentTimeMillis();
		for (int i = 0; i < 1000000000; i++) {
			sb.append(gaga).append(1000000).append(1000000);
			// String st =
			// String.valueOf(gaga)+String.valueOf(1000000)+String.valueOf(1000000);
			String st = sb.toString();
			// System.out.println(st);
			sb.delete(0, st.length());
		}

		System.out.println(System.currentTimeMillis() - start);
	}


}
